<?php
/**
 * Created by IntelliJ IDEA.
 * User: fang.cai.liang@aliyun.com
 * Date: 2017/7/4
 * Time: 14:19
 */

namespace nflow;


/**
 * Class ServiceProvider
 * @package nflow
 */
class ServiceProvider
{
    /**
     * 服务提供方的名称 就是 config.php 中 的 key
     * @var string
     */
    private $providerName;

    /**
     * config.php 文件的内容
     * @var null
     */
    private $conf = null;

    /**
     * 具体某个 API 提供商的实例
     * @var
     */
    private $instance;

    /**
     * 
     * ServiceProvider constructor.
     * @param string $providerName 服务提供方的名称,不提供的话由 chooseOperator 方法来选择
     */
    function __construct($phone, $providerName = '')
    {
        if(Utils::isPhone($phone)){
            require_once __DIR__.'/constants.php';
            $this->parseConfig();
            $this->providerName = $this->chooseOperator($phone, $providerName);
        }
    }

    /**
     * 根据 $phone, $providerName 来返回一个 API 供应商
     * 1. 如果 指定了 $providerName 则就是用指定的
     * 2. 如果没有指定, 则根据电话号码解析, 不同的手机号码运营商,可配置不同的 API 提供商, 如果有多个供应商 则从中随机选择一个
     * 3. 如果该 手机号码运营商,没有配置 API 提供商, 则从现有的所有供应商中随机选择一个
     * @param $phone
     * @param $providerName
     * @return mixed
     * @throws \Exception
     */
    private function chooseOperator($phone, $providerName){
        if(!empty($providerName)){
            return $providerName;
        }
        $operator = Utils::getOperator($phone);
        if(is_null($operator)){
            throw new \Exception("无法确认电话 $phone 的所属运营商!", 10010);
        }
        $operatorProviderList = $this->conf['operator_provider_map'][$operator];
        if(!empty($operatorProviderList)){
            return $operatorProviderList[array_rand($operatorProviderList)];
        }

        $providerList = array_keys($this->conf['operator_list']);
        return $providerList[array_rand($providerList)];
    }

    /**
     * 加载 config.php 文件
     * @throws \Exception
     */
    private function parseConfig(){
        $path = __DIR__.'/config.php';
        $this->conf = include $path;
        if(!is_array($this->conf)){
            throw new \Exception('配置文件不合法, 没有返回一个数组!', 10003);
        }
    }

    /**
     * 实例化 API 供应商
     * @return mixed
     * @throws \Exception
     */
    private function getInstance(){
        if(empty($this->instance)){
            $this->instance = Factory::getInstance($this->providerName, $this->conf['provider_list'][$this->providerName]);
        }
        return $this->instance; 
    }

    /**
     * 调用 供应商 提供的 相关方法
     * @param $method
     * @param $params
     * @return mixed
     */
    public function __call($method, $params){
        return call_user_func_array([$this->getInstance(), $method], $params);
    }

    /**
     * 返回最终使用的那个厂商的名字
     * @return string
     */
    public function getProviderName(){
        return $this->providerName;
    }
}